package dev.marsh.sniper.ar.tracker;

import android.content.Context;
import android.util.Log;
import dev.marsh.sniper.core.BuildConfig;
import dev.marsh.sniper.core.R;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import org.opencv.core.Mat;
import org.opencv.core.MatOfRect;
import org.opencv.core.Size;
import org.opencv.objdetect.CascadeClassifier;

public class JavaDetectionTracker implements Tracker {
    private static final String TAG = "JavaDetectionTracker";
    private static final int TYPE_CAMERA = 111111;
    public static final int TYPE_PHOTO = 222222;

    private CascadeClassifier mJavaDetector;

    public JavaDetectionTracker(Context context) {
        try {
            File cascadeDir = context.getDir("cascade", Context.MODE_PRIVATE);
            File cascadeFile = new File(cascadeDir, "cascade.xml");
            if (!cascadeFile.exists()) {
                InputStream is = context.getResources().openRawResource(R.raw.cascade);
                FileOutputStream os = new FileOutputStream(cascadeFile);

                byte[] buffer = new byte[4096];
                int bytesRead;
                while ((bytesRead = is.read(buffer)) != -1) {
                    os.write(buffer, 0, bytesRead);
                }
                is.close();
                os.close();
            }

            String path = cascadeFile.getAbsolutePath();
            mJavaDetector = new CascadeClassifier(path);
            if (mJavaDetector.empty()) {
                if (BuildConfig.DEBUG) {
                    Log.e(TAG, "Failed to load cascade classifier");
                }
                mJavaDetector = null;
            } else {
                if (BuildConfig.DEBUG) {
                    Log.i(TAG, "Loaded cascade classifier from : " + path);
                }
            }
        } catch (IOException e) {
            if (BuildConfig.DEBUG) {
                Log.e(TAG, "Failed to load cascade. Exception thrown: " + e);
                e.printStackTrace();
            }
        }
    }

    @Override
    public boolean track(Mat src) {
        return track(src, TYPE_CAMERA);
    }

    public boolean track(Mat src, int type) {
        if (mJavaDetector != null) {
            MatOfRect rect = new MatOfRect();

            if (type == TYPE_CAMERA) {
                int height = src.height();
                int size = Math.round(height * 0.2f);
                mJavaDetector.detectMultiScale(src, rect, 1.1, 3, 0, new Size(size, size), new Size());
            } else {
                mJavaDetector.detectMultiScale(src, rect);
            }
            int num = rect.toArray().length;
            if (BuildConfig.DEBUG) {
                Log.e(TAG, "track num: " + num);
            }
            src.release();
            rect.release();
            return num > 0;
        }
        return false;
    }
}
